package va;

import bufmgr.*;
import global.*;
import heap.*;
import index.IndexException;
import iterator.*;

import java.io.IOException;
import java.util.ArrayList;

public class BaseRSIndexScan extends BaseIndexScan {

    public ArrayList<RID> rids;
    public int distance;
    public Vector100Dtype target;
    public int noOfBits;

    public BaseRSIndexScan(IndexType index,
                           String relName,
                           String indexName,
                           AttrType[] types,
                           short[] str_sizes,
                           int noInFields,
                           int noOutFields,
                           FldSpec[] outFields,
                           CondExpr[] selects,
                           int fldNum,
                           Vector100Dtype target,
                           int distance,
                           int noOfBits) throws IndexException, HFException, HFBufMgrException, HFDiskMgrException, IOException, InvalidTupleSizeException, InvalidTypeException, FileScanException, TupleUtilsException, InvalidRelation, JoinsException, PageNotReadException, PredEvalException, UnknowAttrType, FieldNumberOutOfBoundException, WrongPermat {
        super(index, relName, indexName, types, str_sizes, noInFields, noOutFields, outFields, selects, fldNum);
        this.distance = distance;
        this.target = target;
        this.noOfBits = noOfBits;
    }

    /*
	 * Retrieves the next tuple from the index that falls within the specified range
	 * General procedure:
	 * 	- Cycle through the RIDs returned from the VAFileScan of vectors that *potentially* fall within the desired range
	 *  - Grab the actual tuple from the database
	 *  - Check and see if the tuple actually is within the desired distance - if so, return it
	 * @see iterator.Iterator#get_next()
	 */

    @Override
    public Tuple get_next() throws Exception {

        while (this.rids.size() > 0) {
            RID rid = this.rids.remove(0);
            Tuple tuple = getRecordDirect(rid);
            tuple.setHdr((short) this.schema.attrType.length, this.schema.attrType, this.schema.attrSize);
            Vector100Dtype vector = tuple.get100DVectFld(this.fldNum);
            double vectorDistance = Vector100Dtype.Distance(this.target, vector);
            if ((int)vectorDistance <= this.distance) {
                // The RIDs are only approximations. Thus, make sure that the actual distance is desirable
                return this.formatTuple(tuple);
            }
        }
        return null; // None found
    }

}
